package javabase.demo03;

import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CopyOnWriteArrayList;

public class ConcurrentCollectionPractice {
    public static void main(String[] args) {
        // 1. CopyOnWriteArrayList
        demonstrateCopyOnWriteArrayList();

        // 2. ConcurrentLinkedQueue
        demonstrateConcurrentLinkedQueue();

        // 3. ConcurrentHashMap
        demonstrateConcurrentHashMap();
    }

    private static void demonstrateCopyOnWriteArrayList() {
        System.out.println("\n=== CopyOnWriteArrayList ===");

        List<String> list = new CopyOnWriteArrayList<>();

        // 启动一个线程不断读取
        Thread reader = new Thread(() -> {
            while (true) {
                try {
                    for (String item : list) {
                        System.out.println("读取: " + item);
                    }
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    break;
                }
            }
        });

        reader.start();

        // 主线程添加元素
        for (int i = 0; i < 5; i++) {
            String item = "Item" + i;
            list.add(item);
            System.out.println("添加: " + item);
            try {
                Thread.sleep(150);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        reader.interrupt();

        System.out.println("最终列表: " + list);
    }

    private static void demonstrateConcurrentLinkedQueue() {
        System.out.println("\n=== ConcurrentLinkedQueue ===");

        Queue<String> queue = new ConcurrentLinkedQueue<>();

        // 生产者线程
        Thread producer = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                String item = "Product" + i;
                queue.offer(item);
                System.out.println("生产: " + item);
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        // 消费者线程
        Thread consumer = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                String item = queue.poll();
                if (item != null) {
                    System.out.println("消费: " + item);
                }
                try {
                    Thread.sleep(150);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        producer.start();
        consumer.start();

        try {
            producer.join();
            consumer.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("队列剩余: " + queue.size());
    }

    private static void demonstrateConcurrentHashMap() {
        System.out.println("\n=== ConcurrentHashMap ===");

        ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();

        // 多个线程同时操作
        Thread[] threads = new Thread[5];
        for (int i = 0; i < threads.length; i++) {
            final int threadId = i;
            threads[i] = new Thread(() -> {
                for (int j = 0; j < 10; j++) {
                    String key = "Key" + (threadId * 10 + j);
                    map.put(key, threadId * 10 + j);
                    System.out.println("线程" + threadId + " 添加: " + key);

                    // 使用线程安全的方法
                    map.computeIfPresent(key, (k, v) -> v + 1);
                }
            });
        }

        for (Thread thread : threads) {
            thread.start();
        }

        for (Thread thread : threads) {
            try {
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        System.out.println("最终映射大小: " + map.size());

        // 遍历
        map.forEach((k, v) -> System.out.println(k + " => " + v));

        // 搜索
        String result = map.search(100, (k, v) -> v > 40 ? k : null);
        System.out.println("搜索值>40的键: " + result);

        // 归约
        Integer sum = map.reduce(100, (k, v) -> v, (v1, v2) -> v1 + v2);
        System.out.println("所有值的和: " + sum);
    }
}
